package com.cts.tmall.biz.service;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cts.tmall.com.exception.SystemException;
import com.cts.tmall.com.message.RspCode;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.List;

public class BaseService<T> {

    @Autowired
    private BaseMapper<T> mapper;

    public BaseMapper<T> getMapper() {
        return mapper;
    }

    @Transactional(rollbackFor = Exception.class)
    public T save(T entity) {
        if (entity == null) {
            throw new SystemException(RspCode.FAILURE_SYSTEM, "[" + tableName() + "]表新增失败！请求参数为空！");
        }
        int insertCount = mapper.insert(entity);
        if (insertCount != 1) {
            throw new SystemException(RspCode.FAILURE_SYSTEM, "数据新增失败！");
        }
        return entity;
    }

    @Transactional(rollbackFor = Exception.class)
    public void deleteById(Serializable id) {
        if (ObjectUtils.isEmpty(id)) {
            throw new SystemException(RspCode.FAILURE_SYSTEM, "[" + tableName() + "]表删除失败！主键为空！");
        }
        int deleteCount = mapper.deleteById(id);
        if (deleteCount != 1) {
            throw new SystemException(RspCode.FAILURE_SYSTEM, "数据删除失败！");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void deleteByIds(List<Serializable> ids) {
        if (ObjectUtils.isEmpty(ids)) {
            throw new SystemException(RspCode.FAILURE_SYSTEM, "[" + tableName() + "]表批量删除失败！主键为空！");
        }
        int deleteCount = mapper.deleteBatchIds(ids);
        if (deleteCount != ids.size()) {
            throw new SystemException(RspCode.FAILURE_SYSTEM, "数据批量删除失败！");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public T updateById(T entity) {
        if (ObjectUtils.isEmpty(entity)) {
            throw new SystemException(RspCode.FAILURE_SYSTEM, "[" + tableName() + "]表修改失败！请求参数为空！");
        }
        if (ObjectUtils.isEmpty(idValue(entity))) {
            throw new SystemException(RspCode.FAILURE_SYSTEM, "[" + tableName() + "]表修改失败！主键为空！");
        }
        int updateCount = mapper.updateById(entity);
        if (updateCount != 1) {
            throw new SystemException(RspCode.FAILURE_SYSTEM, "数据修改失败！");
        }
        return mapper.selectById(idValue(entity));
    }

    public Page<T> queryPage(T entity, long pageNumb, long pageSize) {
        return mapper.selectPage(new Page<>(pageNumb, pageSize), ObjectUtils.isEmpty(entity) ? Wrappers.emptyWrapper() : Wrappers.query(entity));
    }

    public List<T> queryList(T entity) {
        return mapper.selectList(ObjectUtils.isEmpty(entity) ? Wrappers.emptyWrapper() : Wrappers.query(entity));
    }

    public T queryById(Serializable id) {
        if (ObjectUtils.isEmpty(id)) {
            throw new SystemException(RspCode.FAILURE_SYSTEM, "[" + tableName() + "]表查询失败！主键为空！");
        }
        return mapper.selectById(id);
    }

    /**
     * 获取Entity类
     *
     * @return
     */
    private Class<T> entityClass() {
        Class<T> entityClass = (Class<T>) ReflectionKit.getSuperClassGenericType(getClass(), 0);
        com.baomidou.mybatisplus.core.toolkit.Assert.notNull(entityClass, "BaseService指定泛型不正确！");
        return entityClass;
    }

    /**
     * 获取表信息元数据
     *
     * @return
     */
    private TableInfo tableInfo() {
        TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass());
        com.baomidou.mybatisplus.core.toolkit.Assert.notNull(tableInfo, entityClass().getName() + "对应表信息不存在！");
        return tableInfo;
    }

    /**
     * 表名
     *
     * @return
     */
    private String tableName() {
        return tableInfo().getTableName();
    }

    /**
     * 主键字段
     *
     * @return
     */
    private String idField() {
        String keyField = tableInfo().getKeyProperty();
        com.baomidou.mybatisplus.core.toolkit.Assert.notEmpty(keyField, entityClass() + "实体主键字段不存在！");
        return keyField;
    }

    /**
     * 主键字段值
     *
     * @param entity
     * @return
     */
    private Serializable idValue(T entity) {
        return (Serializable) ReflectionKit.getFieldValue(entity, idField());
    }

}
